package cn.huixh.blindbox.service.impl;

import cn.huixh.blindbox.common.Common;
import cn.huixh.blindbox.common.ReturnCode;
import cn.huixh.blindbox.exception.impl.BizException;
import cn.huixh.blindbox.mapper.AccountMapper;
import cn.huixh.blindbox.pojo.po.Account;
import cn.huixh.blindbox.service.TokenService;
import cn.huixh.blindbox.utils.JwtUtil;
import cn.huixh.blindbox.utils.RedisUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author huixh
 * @version 1.0
 * @date 2022/5/13 13:13
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TokenServiceImpl extends ServiceImpl< AccountMapper, Account > implements TokenService {

    final JwtUtil jwtUtil;

    final RedisUtil redisUtil;


    /**
     * 校验token
     *
     * @param token token
     */
    @Override
    public void tokenVerify(String token) {
        Assert.isTrue(jwtUtil.verify(token), "token验证失败！");
    }

    /**
     * 从 token 中获取用户对象id
     *
     * @param token token
     * @return id
     */
    @Override
    public String getAccountId(String token) {
        return jwtUtil.getPayload("jti", token);
    }

    /**
     * 从 token 中获取用户对象 email
     *
     * @param token token
     * @return email
     */
    @Override
    public String getAccountEmail(String token) {
        return jwtUtil.getPayload("email", token);
    }

    /**
     * 从 token 中获取用户对象
     *
     * @param token token
     * @return account
     */
    @Override
    public Account getAccountByToken(String token) {
        tokenVerify(token);
        return getById(getAccountId(token));
    }

    /**
     * 获取token
     *
     * @param email 邮箱
     * @return token
     */
    @Override
    public String getToken(String email) {
        AtomicReference< String > token = new AtomicReference<>("");
        Optional< Account > optional = Optional.ofNullable(getOne(Wrappers.< Account >lambdaQuery().eq(Account::getEmail, email), false));
        optional.ifPresentOrElse(
                account -> {
                    token.set(jwtUtil.createToken(account.getId(), account.getEmail()));
                    redisUtil.set("token_" + account.getId(), token, Common.EXPIRE_TIME);
                },
                () -> {
                    log.error("数据库账户与邮箱不匹配！");
                    throw new BizException(ReturnCode.RC500);
                }
        );
        log.info("token {}", token.get());
        return token.get();
    }
}
